﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GrafosWindows.Model;
using GrafosWindows.Persistencia;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GrafosWindows.Testes
{
    [TestClass]    
    public class TesteGrafo
    {
        private string[] arquivoGrafo01;
        private string[] arquivoGrafo02;
        private string[] arquivoGrafo04;

        [TestInitialize]
        public void TestInitialize()
        {
            arquivoGrafo01 = IOUtils.ReadTxtFile("Arquivos\\Grafo01.txt");
            arquivoGrafo02 = IOUtils.ReadTxtFile("Arquivos\\Grafo02.txt");
            arquivoGrafo04 = IOUtils.ReadTxtFile("Arquivos\\Grafo04.txt");
        }

        [TestMethod]
        public void TestCriarGrafos()
        {
            Grafo grafo01 = new Grafo(arquivoGrafo01);
            Assert.AreEqual(3, grafo01.Cardinalidade, "Cardinalidade do Grafo 1 diferente de 3. Valor = "+grafo01.Cardinalidade);
            Assert.AreEqual(3, grafo01.ListaVertices.Count, "Lista de nós do Grafo 1 diferente de 3. Valor = " + grafo01.ListaVertices.Count);

            int[,] matrizAdjascencia = new int[,]{  {0, 1, 1}, 
                                                    {1, 0, 0}, 
                                                    {1, 0, 0}};
            int[,] matrizAdjascenciaGrafo = grafo01.MatrizAdjascencia;
            for (int i = 0; i < matrizAdjascencia.GetLength(0); i++)
            {
                for (int j = 0; j < matrizAdjascencia.GetLength(1); j++)
                {
                    Assert.AreEqual(matrizAdjascencia[i, j], matrizAdjascenciaGrafo[i, j], 
                        "Valores da matriz de adjascência diferentes na posição " + i + ", " + j + " > " + 
                        matrizAdjascencia[i, j] + " != " + matrizAdjascenciaGrafo[i, j]);
                }    
            }

            Vertice vertice1 = grafo01.HashVertices["V1"];
            Assert.AreEqual(2, vertice1.Cardinalidade, "Cardinalidade do Vertice 1 diferente de 2. Valor = " + vertice1.Cardinalidade);

            Grafo grafo02 = new Grafo(arquivoGrafo02);
            Assert.AreEqual(6, grafo02.Cardinalidade, "Cardinalidade do Grafo 2 diferente de 6. Valor = " + grafo02.Cardinalidade);
            Assert.AreEqual(6, grafo02.ListaVertices.Count, "Lista de nós do Grafo 2 diferente de 6. Valor = " + grafo02.ListaVertices.Count);

            matrizAdjascencia = new int[,] { { 0 ,1, 0, 0, 1, 0}, 
                                             { 1, 0, 1, 0, 1, 0}, 
                                             { 0, 1, 0, 1, 0, 0}, 
                                             { 0, 0, 1, 0, 1, 1},
                                             { 1, 1, 0, 1, 0, 0}, 
                                             { 0, 0, 0, 1, 0, 0}};
            matrizAdjascenciaGrafo = grafo02.MatrizAdjascencia;
            for (int i = 0; i < matrizAdjascencia.GetLength(0); i++)
            {
                for (int j = 0; j < matrizAdjascencia.GetLength(1); j++)
                {
                    Assert.AreEqual(matrizAdjascencia[i, j], matrizAdjascenciaGrafo[i, j],
                        "Valores da matriz de adjascência diferentes na posição " + i + ", " + j + " > " +
                        matrizAdjascencia[i, j] + " != " + matrizAdjascenciaGrafo[i, j]);
                }
            }
        }

        [TestMethod]
        public void TestCaminhos()
        {
            Grafo grafo01 = new Grafo(arquivoGrafo01);

            //Verificar se existe caminho

            //Pegando todos os vértices
            Vertice v1 = grafo01.HashVertices["V1"];
            Vertice v2 = grafo01.HashVertices["V2"];
            Vertice v3 = grafo01.HashVertices["V3"];

            Assert.AreEqual(true, grafo01.ExisteCaminho(v1, v1), "Erro: Resposta diz que não há caminho entre v1 e v1, mas existe");
            Assert.AreEqual(true, grafo01.ExisteCaminho(v1, v2), "Erro: Resposta diz que não há caminho entre v1 e v2, mas existe");
            Assert.AreEqual(true, grafo01.ExisteCaminho(v1, v3), "Erro: Resposta diz que não há caminho entre v1 e v3, mas existe");
            Assert.AreEqual(true, grafo01.ExisteCaminho(v3, v1), "Erro: Resposta diz que não há caminho entre v3 e v3, mas existe");
            Assert.AreEqual(true, grafo01.ExisteCaminho(v2, v3), "Erro: Resposta diz que não há caminho entre v2 e v3, mas existe");

            Grafo grafo02 = new Grafo(arquivoGrafo02);

            v1 = grafo02.HashVertices["V1"];
            v2 = grafo02.HashVertices["V2"];
            v3 = grafo02.HashVertices["V3"];
            Vertice v6 = grafo02.HashVertices["V6"];

            Assert.AreEqual(true, grafo02.ExisteCaminho(v1, v1), "Erro: Resposta diz que não há caminho entre v1 e v1, mas existe");
            Assert.AreEqual(true, grafo02.ExisteCaminho(v1, v2), "Erro: Resposta diz que não há caminho entre v1 e v2, mas existe");
            Assert.AreEqual(true, grafo02.ExisteCaminho(v1, v6), "Erro: Resposta diz que não há caminho entre v1 e v6, mas existe");
            Assert.AreEqual(true, grafo02.ExisteCaminho(v6, v1), "Erro: Resposta diz que não há caminho entre v6 e v1, mas existe");
        }

        [TestMethod]
        public void TestDijsktra()
        {
            Grafo grafo01 = new Grafo(arquivoGrafo01);
            Grafo grafo04 = new Grafo(arquivoGrafo04);

            //Verificar se existe caminho

            //Pegando todos os vértices

            #region Teste de caminho mínimo de v1 para v2 no grafo 01
            Vertice v1 = grafo01.HashVertices["V1"];
            Vertice v2 = grafo01.HashVertices["V2"];
            Vertice v3 = grafo01.HashVertices["V3"];

            List<Vertice> caminhoPrevisto = new List<Vertice>();
            List<Vertice> caminhoCalculado = new List<Vertice>();

            caminhoPrevisto.Add(v2);
            caminhoPrevisto.Add(v1);

            caminhoCalculado = grafo01.CaminhoDijkstra(v1, v2);

            Assert.AreEqual(caminhoPrevisto.Count, caminhoCalculado.Count, "Tamanho do caminho calculado é diferente do caminho previsto!");

            for (int i = 0; i < caminhoPrevisto.Count; i++)
            {
                Assert.AreEqual(caminhoPrevisto[i], caminhoCalculado[i], caminhoPrevisto[i] + " diferente de " + caminhoCalculado[i]);
            }
            #endregion

            #region Teste de caminhos mínimos no grafo 04
            v1 = grafo04.HashVertices["V1"];
            v2 = grafo04.HashVertices["V2"];
            v3 = grafo04.HashVertices["V3"];
            Vertice v5 = grafo04.HashVertices["V5"];
            Vertice v7 = grafo04.HashVertices["V7"];
            Vertice v8 = grafo04.HashVertices["V8"];
            Vertice v9 = grafo04.HashVertices["V9"];

            //v1 - v5
            caminhoPrevisto.Clear();
            caminhoPrevisto.Add(v5);
            caminhoPrevisto.Add(v1);

            caminhoCalculado = grafo04.CaminhoDijkstra(v1, v5);

            Assert.AreEqual(caminhoPrevisto.Count, caminhoCalculado.Count, "Tamanho do caminho calculado é diferente do caminho previsto!");

            for (int i = 0; i < caminhoPrevisto.Count; i++)
            {
                Assert.AreEqual(caminhoPrevisto[i], caminhoCalculado[i], caminhoPrevisto[i] + " diferente de " + caminhoCalculado[i]);
            }
            //v1 - v9 - v7 - v8
            caminhoPrevisto.Clear();
            caminhoPrevisto.Add(v8);
            caminhoPrevisto.Add(v7);
            caminhoPrevisto.Add(v9);
            caminhoPrevisto.Add(v1);

            caminhoCalculado = grafo04.CaminhoDijkstra(v1, v8);

            Assert.AreEqual(caminhoPrevisto.Count, caminhoCalculado.Count, "Tamanho do caminho calculado é diferente do caminho previsto!");

            for (int i = 0; i < caminhoPrevisto.Count; i++)
            {
                Assert.AreEqual(caminhoPrevisto[i], caminhoCalculado[i], caminhoPrevisto[i] + " diferente de " + caminhoCalculado[i]);
            }

            //v8 - v3 - v2 - v5
            caminhoPrevisto.Clear();
            caminhoPrevisto.Add(v5);
            caminhoPrevisto.Add(v2);
            caminhoPrevisto.Add(v3);
            caminhoPrevisto.Add(v8);

            caminhoCalculado = grafo04.CaminhoDijkstra(v8, v5);

            Assert.AreEqual(caminhoPrevisto.Count, caminhoCalculado.Count, "Tamanho do caminho calculado é diferente do caminho previsto!");

            for (int i = 0; i < caminhoPrevisto.Count; i++)
            {
                Assert.AreEqual(caminhoPrevisto[i], caminhoCalculado[i], caminhoPrevisto[i] + " diferente de " + caminhoCalculado[i]);
            }
            #endregion
        }
    }
}
